package com.ugoodtech.mdcc.core.aop;

import com.ugoodtech.mdcc.core.dto.JsonResponse;
import java.lang.reflect.Parameter;
import java.util.Arrays;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
@Aspect
@Slf4j
public class LogAspect {


	@Pointcut("@annotation(com.ugoodtech.mdcc.core.annotation.LogAt)")
	public void pointCut() {
	}

	@Around("pointCut()")
	public Object around(ProceedingJoinPoint point) {
		long startTime = System.nanoTime();
		val methodName = point.getSignature().getName();

		val argNames = Stream.of(((MethodSignature) point.getSignature()).getMethod().getParameters()).map(Parameter::getName).collect(Collectors.toList());
		val args = Arrays.asList(point.getArgs());
		val argMap = argNames.stream().collect(Collectors.toMap(
			k -> k,
			k -> args.get(argNames.indexOf(k)) == null ? "null" : args.get(argNames.indexOf(k)),
			(f, s) -> f
		));


		log.info("request api : {}", methodName);
		log.info("request parameters : ".concat(argMap.toString()));

		try{
				val ret = point.proceed();
				if(null == ret) {
					return ret;
				}
				log.info("response : {}", ret.toString());
				val cost = (System.nanoTime() - startTime) / 1000000;
				if (cost > 500) {
					log.warn("api cost more than 500 ms, api name : {}, cost : {}", methodName,
						cost);
				}
				return ret;
			}catch (Exception error) {
				log.error(".alarm api deal error for :", error);
				return JsonResponse.errorResponseWithError("error", "error");
			} catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }
}
